home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
- *
- * (b) If this Sample Code is distributed as part of the Display PostScript
- * System Software Development Kit from Adobe Systems Incorporated,
- * then this copy is designated as Development Software and its use is
- * subject to the terms of the License Agreement attached to such Kit.
- *
- * (c) If this Sample Code is distributed independently, then the following
- * terms apply:
- *
- * (d) This file may be freely copied and redistributed as long as:
- * 1) Parts (a), (d), (e) and (f) continue to be included in the file,
- * 2) If the file has been modified in any way, a notice of such
- * modification is conspicuously indicated.
- *
- * (e) PostScript, Display PostScript, and Adobe are registered trademarks of
- * Adobe Systems Incorporated.
- *
- * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
- * CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
- * AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
- * ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
- * OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
- * WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
- * WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
- * DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
- * OF THIRD PARTY RIGHTS.
- */
-
- /*
- * ImportApp.m
- *
- * This class performs some of the global functions necessary to
- * manage the application.
- *
- * Several application wide resources are retained as
- * instance variables. Examples are the hitPoint and
- * upathBuffer buffers and the hitSetting value.
- *
- * Version: 2.0
- * Author: Ken Fromm
- */
-
- #import "ImportApp.h"
- #import "Document.h"
- #import "DrawingView.h"
- #import "ImportPanel.h"
- #import "Preferences.h"
- #import "SaveAsPanel.h"
-
- #import "DrawingViewWraps.h"
-
- #import <appkit/NXCursor.h>
- #import <appkit/NXImage.h>
- #import <appkit/Matrix.h>
- #import <appkit/Menu.h>
- #import <appkit/MenuCell.h>
- #import <appkit/defaults.h>
- #import <appkit/nextstd.h>
-
- #import <objc/List.h>
- #import <sys/param.h>
- #import <string.h>
-
- struct cursorRecord {
- char *name;
- NXPoint hotspot;
- };
-
- const static struct cursorRecord cursors[] = {
- {NULL, 0.0, 0.0}, /* Select */
- {"cursorZoomUp.tiff", 8.0, 8.0},
- {"cursorRotate1.tiff", 8.0, 8.0},
- {"cursorZoomDown.tiff", 8.0, 8.0},
- {"cursorRotate2.tiff", 6.0, 4.0},
- {"cursorImport.tiff", 2.0, 1.0},
- {NULL, 0.0, 0.0} /* Place */
- };
-
- char ControlFont[ ] = "ControlPointsFont";
-
- @implementation ImportApp
-
- /*
- * Sets the updateAction for every menu item which sends to the
- * First Responder (i.e. their target is nil). When autoupdate is on,
- * every event will be followed by an update of each of the menu items
- * which is visible. This keep all unavailable menu items dimmed out
- * so that the user knows what options are available at any given time.
- * Returns the activate menu if is found in this menu.
- */
- static void initMenu(id menu)
- {
- int count;
- id matrix, cell;
- id matrixTarget, cellTarget;
-
- matrix = [menu itemList];
- matrixTarget = [matrix target];
-
- count = [matrix cellCount];
- while (count--)
- {
- cell = [matrix cellAt:count :0];
- cellTarget = [cell target];
- if (!matrixTarget && !cellTarget)
- [cell setUpdateAction:@selector(menuItemUpdate:) forMenu:menu];
- else if ([cell hasSubmenu])
- initMenu(cellTarget);
- }
- }
-
- /*
- * Checks to see if the passed window's delegate is a Document
- * instance. If it is, it returns that document, otherwise it returns nil.
- */
- static id documentInWindow(id window)
- {
- id document = [window delegate];
-
- return [document isKindOf:[Document class]] ? document : nil;
- }
-
- /*
- * Searches the window list looking for a Document with the specified
- * name. Returns the window containing the document if found.
- * If name == NULL then the first document found is returned.
- */
- static id findDocument(const char *name)
- {
- int count;
- id document, window, windowList;
-
- windowList = [NXApp windowList];
- count = [windowList count];
- while (count--)
- {
- window = [windowList objectAt:count];
- document = documentInWindow(window);
-
- if (document && (!name || !strcmp([document filename], name)))
- return window;
- }
-
- return nil;
- }
-
- /*
- * Opens a file with the given name in the specified directory.
- * If we already have that file open, it is ordered front.
- * Returns the document if successful, nil otherwise.
- */
- static id openFile(const char *directory, const char *name, BOOL display)
- {
- id window;
-
- char buffer[MAXPATHLEN+1], path[MAXPATHLEN+1];
-
- if (name && *name)
- {
- if (!directory)
- {
- directory = ".";
- }
- else if (*directory != '/')
- {
- strcpy(buffer, "./");
- strcat(buffer, directory);
- directory = buffer;
- }
-
- if (!chdir(directory) && getwd(path))
- {
- strcat(path, "/");
- strcat(path, name);
- window = findDocument(path);
- if (window)
- {
- if (display)
- [window makeKeyAndOrderFront:window];
- return [window delegate];
- }
- else
- return [Document newFromFile:path];
- }
- else
- NXRunAlertPanel("Open", "Invalid path: %s", "OK", NULL, NULL, directory);
- }
-
- return nil;
- }
-
- /*
- * Allocate a buffer for use by any drawing view to send
- * data to the PostScript server.
- *
- * Allocate this buffer for use by any drawing view to
- * use as the hitdetection userpath. Initialize the description
- * since most of the components will remain the same.
- */
- + new
- {
- int i;
-
- self = [super new];
-
- [self setAutoupdate:YES];
-
- PSWDefineFont(ControlFont);
- hitSetting = 4.0;
- contextFlag = imagingFlag = YES;
-
- NX_MALLOC(upathBuffer.pts, float, PTS_BUFFER);
- NX_MALLOC(upathBuffer.ops, char, OPS_BUFFER);
-
- NX_MALLOC(hitPoint.pts, float, PTS_HITPOINT);
- NX_MALLOC(hitPoint.ops, char, OPS_HITPOINT);
-
- for (i = 0; i < PTS_HITPOINT; i++)
- hitPoint.pts[i] = 0;
- hitPoint.num_pts = i;
-
- i = 0;
- hitPoint.ops[i++] = dps_setbbox;
- hitPoint.ops[i++] = dps_moveto;
- hitPoint.ops[i++] = dps_rlineto;
- hitPoint.ops[i++] = dps_rlineto;
- hitPoint.ops[i++] = dps_rlineto;
- hitPoint.ops[i++] = dps_closepath;
- hitPoint.num_ops = i;
-
- return self;
- }
-
- /* Initializes the defaults. */
- + initialize
- {
- const NXDefaultsVector EpsfDefaults = {
- { "Quit", NULL },
- { NULL, NULL }
- };
-
- NXRegisterDefaults("Epsf", EpsfDefaults);
-
- return self;
- }
-
- - free
- {
- if (upathBuffer.pts)
- NX_FREE(upathBuffer.pts);
- if (upathBuffer.ops)
- NX_FREE(upathBuffer.ops);
- if (hitPoint.pts)
- NX_FREE(hitPoint.pts);
- if (hitPoint.ops)
- NX_FREE(hitPoint.ops);
-
- return [super free];
- }
-
- - setToolPanel:anObject
- {
- toolpanelId = anObject;
-
- return self;
- }
-
- - setToolMatrix:anObject
- {
- toolmatrixId = anObject;
-
- return self;
- }
-
- - setSaveAccessory:anObject
- {
- [[SaveAsPanel new] setAccessoryView:anObject];
-
- return self;
- }
-
- - setImportAccessory:anObject
- {
- [[ImportPanel new] setImportAccessory:anObject];
-
- return self;
- }
-
- /* Calculate the position for the next window. */
- - getPosition:(NXPoint *)location forSize:(NXSize *)winSize
- {
- int col, row;
-
- col = (numWindows/NUMPERCOL) % NUMCOLUMNS;
- row = numWindows % NUMPERCOL;
-
- location->x = WINDOWSTARTX + (col * OFFSETLEFT) + (row * OFFSETX);
- location->y = WINDOWSTARTY - winSize->height - (row * OFFSETY);
-
- numWindows++;
-
- return self;
- }
-
- /*
- * Teaching aids
- */
- - setContextFlag:sender
- {
- if (!contextFlag)
- [[sender selectedCell] setTitle:"Separate Context On"];
- else
- [[sender selectedCell] setTitle:"Separate Context Off"];
-
- contextFlag = !contextFlag;
-
- return self;
- }
-
- - (BOOL) contextFlag
- {
- return contextFlag;
- }
-
- - setShowEpsfFlag:sender
- {
- if (!showEpsfFlag)
- [[sender selectedCell] setTitle:"Show Epsf On"];
- else
- [[sender selectedCell] setTitle:"Show Epsf Off"];
-
- showEpsfFlag = !showEpsfFlag;
-
- return self;
- }
-
- - (BOOL) showEpsfFlag
- {
- return showEpsfFlag;
- }
-
- - setShowBufferFlag:sender
- {
- if (!showBufferFlag)
- [[sender selectedCell] setTitle:"Show Buffer On"];
- else
- [[sender selectedCell] setTitle:"Show Buffer Off"];
-
- showBufferFlag = !showBufferFlag;
-
- if (showBufferFlag)
- [[[self currentDocument] drawingView] showBuffer:self];
- else
- [[[self currentDocument] drawingView] hideBuffer:self];
-
- return self;
- }
-
- - (BOOL) showBufferFlag
- {
- return showBufferFlag;
- }
-
- /* Change the menu title and toggle the trace boolean. */
- - setTracingFlag:sender
- {
- if (!tracingFlag)
- [[sender selectedCell] setTitle:"Trace On"];
- else
- [[sender selectedCell] setTitle:"Trace Off"];
-
- tracingFlag = !tracingFlag;
-
- return self;
- }
-
- - (BOOL) tracingFlag
- {
- return tracingFlag;
- }
-
- - setImagingFlag:sender
- {
- imagingFlag = [sender state];
- [[[self currentDocument] drawingView] display];
-
- return self;
- }
-
- - (BOOL) imagingFlag
- {
- return imagingFlag;
- }
-
- - setHitSetting:sender
- {
- hitSetting = [sender floatValue];
-
- return self;
- }
-
- - (float) hitSetting
- {
- return hitSetting;
- }
-
- - (UPath *) hitPoint;
- {
- return &hitPoint;
- }
-
- - (UPath *) upathBuffer;
- {
- return &upathBuffer;
- }
-
- - currentDocument
- {
- return documentInWindow(mainWindow);
- }
-
- - (const char *)currentDirectory
- {
- const char *retval = [[self currentDocument] directory];
-
- if (!retval || !*retval)
- retval = [[OpenPanel new] directory];
-
- return retval;
- }
-
- /* Open a new document. */
- - new:sender
- {
- [Document new];
-
- return self;
- }
-
- /*
- * Called by pressing Open... in the Window menu.
- */
- - open:sender
- {
- id openpanel;
-
- char path[MAXPATHLEN+1];
-
- const char *directory;
-
- const char *const *files;
-
- static const char *const filetype[2] = {"adb", NULL};
-
- directory = NULL;
- directory = [[self currentDocument] directory];
- if (!directory)
- if (getwd(path))
- directory = path;
- openpanel = [[ImportPanel new] setOpen];
- if ([openpanel runModalForDirectory:directory file:NULL types:filetype])
- {
- files = [openpanel filenames];
- directory = [openpanel directory];
- while (files && *files)
- {
- openFile(directory, *files, YES);
- files++;
- }
- }
-
- return self;
- }
-
- /*
- * Sends a windowWillClose message to all open Documents
- * before the program terminates.
- */
- - terminate:sender
- {
- int count;
- id window, document;
-
- count = [windowList count];
- while (count--)
- {
- window = [windowList objectAt:count];
- document = documentInWindow(window);
- if (document)
- {
- if ([document windowWillClose:window])
- [window close];
- else
- return self;
- }
- }
-
- return [super terminate:sender];
- }
-
- - setTool:sender
- {
- [self setOperation:[sender selectedTag]];
-
- return self;
- }
-
- - resourcePanel
- {
- if (!resourcePanel)
- [NXApp loadNibSection:"ResourcePanel.nib" owner:self withNames:NO];
-
- return resourcePanel;
- }
-
- /*
- * Return the cursor for the appropriate index. Create
- * one if non-existent.
- */
- - getCursor:(int) index
- {
- id imageId;
-
- if (!cursorIds[index])
- {
- if (cursors[index].name)
- {
- imageId = [NXImage newFromSection:cursors[index].name];
- cursorIds[index]= [NXCursor newFromImage:imageId];
- [cursorIds[index] setHotSpot:&cursors[index].hotspot];
- }
- }
-
- return cursorIds[index];
- }
-
- - cursor
- {
- id imageId;
-
- if (!cursorIds[operation])
- {
- if (cursors[operation].name)
- {
- imageId = [NXImage newFromSection:cursors[operation].name];
- cursorIds[operation]= [NXCursor newFromImage:imageId];
- [cursorIds[operation] setHotSpot:&cursors[operation].hotspot];
- }
- else
- cursorIds[operation] = NXArrow;
- }
-
- return cursorIds[operation];
- }
-
- - (int) operation
- {
- return operation;
- }
-
- - setOperation:(int) newOperation
- {
- id currentDoc;
-
- if (newOperation < OP_FIRST || newOperation > OP_LAST)
- newOperation = OP_SELECT;
- operation = newOperation;
-
- currentDoc = [self currentDocument];
- [[currentDoc window] invalidateCursorRectsForView:[currentDoc drawingView]];
-
- return self;
- }
-
- - clearOperation
- {
- [self setOperation:OP_SELECT];
- [toolmatrixId selectCellWithTag:OP_SELECT];
-
- return self;
- }
-
- /*
- * Application object delegate methods.
- * Messages that would be sent to the delegate are sent to the Application
- * object or a subclass if no delagate exists.
- */
-
- /*
- * Initialize the menus.
- * Sets the tool palette so it never becomes the key window.
- * Check for files to open specified on the command line.
- * If there are no open documents, then open a blank one.
- */
- - appDidInit:sender
- {
- id docId;
- int i;
- char buffer[MAXPATHLEN+1];
- char *directory, *name, *ext;
-
- [toolpanelId removeFromEventMask:NX_KEYDOWNMASK|NX_KEYUPMASK];
- [toolpanelId orderFront:self];
-
- initMenu([NXApp mainMenu]);
-
- if (NXArgc > 1)
- {
- for (i = 1; i < NXArgc; i++)
- {
- strcpy(buffer, NXArgv[i]);
- ext = strrchr(buffer, '.');
- if (!ext || strcmp(ext, ".adb"))
- strcat(buffer, ".adb");
-
- name = strrchr(buffer, '/');
-
- if (name)
- {
- *name++ = '\0';
- directory = buffer;
- }
- else
- {
- name = buffer;
- directory = NULL;
- }
- docId = openFile(directory, name, YES);
- }
- }
-
- /* if none opened, open one */
- if (!findDocument(NULL))
- [self new:self];
-
- if (NXGetDefaultValue([self appName], "Quit"))
- {
- [self activateSelf:YES];
- NXPing();
- [self terminate:self];
- }
-
- return self;
- }
-
- /*
- * This method is performed whenever a user double-clicks on an icon
- * in the Workspace Manager representing an Epsf document.
- */
- - (int)appOpenFile:(const char *)path type:(const char *)type
- {
- char *name;
- char directory[MAXPATHLEN+1];
-
- if (type && !strcmp(type, "adb"))
- {
- strcpy(directory, path);
- name = strrchr(directory, '/');
- if (name)
- {
- *name++ = '\0';
- return (openFile(directory, name, YES) ? YES : NO);
- }
- }
-
- return NO;
- }
-
- /* We accept any number of appOpenFile:type: messages. */
- - (BOOL)appAcceptsAnotherFile:sender
- {
- return YES;
- }
-
- /* Automatic update methods */
-
- /*
- * Method called by all menu items which send their actions to the
- * First Responder. First, if the object which would respond were the
- * action sent down the responder chain also responds to the message
- * validateCommand:, then it is sent validateCommand: to determine
- * whether that command is valid now, otherwise, if there is a responder
- * to the message, then it is assumed that the item is valid.
- * The method returns YES if the cell has changed its appearance (so that
- * the caller (a Menu) knows to redraw it).
- */
- - (BOOL)menuItemUpdate:menuCell
- {
- SEL action;
- id responder, target;
- BOOL enable;
-
- target = [menuCell target];
- enable = [menuCell isEnabled];
-
- if (!target)
- {
- action = [menuCell action];
- responder = [self calcTargetForAction:action];
-
- if ([responder respondsTo:@selector(validateCommand:)])
- enable = [responder validateCommand:menuCell];
- else
- enable = responder ? YES : NO;
- }
-
- if ([menuCell isEnabled] != enable)
- {
- [menuCell setEnabled:enable];
- return YES;
- }
- else
- return NO;
- }
-
- @end
-
-